<?php

namespace Core\StringHandling;

final class URL extends String {

    private $boolAllowAllProtocols;

    // Public read only members.
    private $_Protocol;
    private $_Host;
    private $_Port;
    private $_PathSegments; // This is an instance of StringCollection.
    private $_Filename;
    private $_User;
    private $_Password;
    // Each HTTP variable is also accessible as public read only members.

    function __construct ( $mix = null, $constAllowedProtocols = ALL ) {

        // Break down $constAllowedProtocols.
        $this->boolAllowAllProtocols = ( ALL === ( ALL & $constAllowedProtocols ) ) ? true : false;

        parent::__construct( $mix );


        if ( $mix === REQUEST_URI ) {
            @list( $strPath, $strSearch ) = explode( "?", $_SERVER["REQUEST_URI"], 2 );
        } else {
        
            // Build a pattern to match the URL.

            $strPattern = "#^";

            // Match the protocol.
            $strPattern .= "(ftp|http|https|mysql)"; // Protocol.

            $strPattern .= "://";

            // Match the host.
            $strPattern .= "(";
            $strPattern .= "(?:(1?\d{1,2}|2([0-4]\d|5[0-5]))\.){3}(1?\d{1,2}|2([0-4]\d|5[0-5]))"; // This is an IP.
            $strPattern .= "|";
            $strPattern .= "(?:[a-z\d-]+\.)+"; // This is a domain, minus the TLD.
            $strPattern .= "(?:com|localhost|net|no|org)"; // TODO: This should be a list of the available TLDs, and localhost does not belong here.
            $strPattern .= ")";

            // From here on, everything is optional. We'll deal with it separatly.
            $strPattern .= "(?:/(\S*))?";

            $strPattern .= "$#";


            preg_match_all( $strPattern, $mix, $arrMatches );

            $this->_Protocol = new String( $arrMatches[1][0] );
            $this->_Host = new String( $arrMatches[2][0] );

            if ( isset( $arrMatches[7][0] ) ) {
                @list( $strPath, $strSearch ) = explode( "?", $arrMatches[7][0], 2 );
            }

        }

        if ( isset( $strPath ) ) {
            $arrPath = explode( "/", $strPath );
            for ( $i = 0; $i < count( $arrPath ); $i++ ) {
                if ( $i + 1 == count( $arrPath ) ) {
                    $this->_Filename = new String ( $arrPath[$i] );
                } else {
                    $this->_PathSegments[] = new String ( $arrPath[$i] );
                }
            }
        }

    }

    function __get ( $strMemberName ) {

        switch ( $strMemberName ) {

            case "Protocol":
                return $this->_Protocol;

            case "Host":
                return $this->_Host;

            case "Port":
                return $this->_Port;

            case "PathSegments":
                return $this->_PathSegments;

            case "Filename":
                return $this->_Filename;

            case "User":
                return $this->_User;

            case "Password":
                return $this->_Password;

            default:
                // TODO: Return the query aswell.

        }

    }

    function __set ( $strMemberName, $mixMemberValue ) {

        switch ( $strMemberName ) {

        }

    }

    function __isset ( $strMemberName ) {

        switch ( $strMemberName ) {

            case "Protocol":
                return isset( $this->_Protocol );

            case "Port":
                return isset( $this->_Port );

            case "Filename":
                return isset( $this->_Filename );

            case "";

        }

    }

    function __toString () {

        if ( isset( $this->Protocol ) ) {

            switch ( $this->Protocol ) {

                case "http":
                    $strReturn = "http://" . $this->Host;
                    $strReturn .= ( isset( $this->Port ) ) ? ":" . $this->Port : "";
                    $strReturn .= "/";
                    foreach ( $this->PathSegments as $cstrPathSegment ) {
                        $strReturn .= $cstrPathSegment . "/";
                    }
                    $strReturn .= isset( $this->Filename ) ? $this->Filename : "";
                    break;

                case "mysql":
                    $strReturn = "mysql://" . $this->User . ":" . $this->Password . "@" . $this->Host;
                    break;

            }

        } else {
            
        }

        return $strReturn;

    }

}

?>
